<template>
  <view class="uni-countdown">
    <text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
    <text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text>
    <text v-if="showHour" :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
    <text v-if="showHour" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
    <text v-if="showMinute" :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
    <text v-if="showMinute" :style="[splitorStyle]"
      class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
    <text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
    <text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text>
  </view>
</template>
<script>
  import {
    initVueI18n
  } from '@dcloudio/uni-i18n'
  import messages from './i18n/index.js'
  const {
    t
  } = initVueI18n(messages)
  /**
   * Countdown 倒计时
   * @description 倒计时组件
   * @tutorial https://ext.dcloud.net.cn/plugin?id=25
   * @property {String} backgroundColor 背景色
   * @property {String} color 文字颜色
   * @property {Number} day 天数
   * @property {Number} hour 小时
   * @property {Number} minute 分钟
   * @property {Number} second 秒
   * @property {Number} timestamp 时间戳
   * @property {Boolean} showDay = [true|false] 是否显示天数
   * @property {Boolean} showHour = [true|false] 是否显示小时
   * @property {Boolean} showMinute = [true|false] 是否显示分钟
   * @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符
   * @property {String} splitorColor 分割符号颜色
   * @event {Function} timeup 倒计时时间到触发事件
   * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
   */
  export default {
    name: 'UniCountdown',
    emits: ['timeup'],
    props: {
      showDay: {
        type: Boolean,
        default: true
      },
      showHour: {
        type: Boolean,
        default: true
      },
      showMinute: {
        type: Boolean,
        default: true
      },
      showColon: {
        type: Boolean,
        default: true
      },
      start: {
        type: Boolean,
        default: true
      },
      backgroundColor: {
        type: String,
        default: ''
      },
      color: {
        type: String,
        default: '#333'
      },
      fontSize: {
        type: Number,
        default: 14
      },
      splitorColor: {
        type: String,
        default: '#333'
      },
      day: {
        type: Number,
        default: 0
      },
      hour: {
        type: Number,
        default: 0
      },
      minute: {
        type: Number,
        default: 0
      },
      second: {
        type: Number,
        default: 0
      },
      timestamp: {
        type: Number,
        default: 0
      }
    },
    data() {
      return {
        timer: null,
        syncFlag: false,
        d: '00',
        h: '00',
        i: '00',
        s: '00',
        leftTime: 0,
        seconds: 0
      }
    },
    computed: {
      dayText() {
        return t("uni-countdown.day")
      },
      hourText(val) {
        return t("uni-countdown.h")
      },
      minuteText(val) {
        return t("uni-countdown.m")
      },
      secondText(val) {
        return t("uni-countdown.s")
      },
      timeStyle() {
        const {
          color,
          backgroundColor,
          fontSize
        } = this
        return {
          color,
          backgroundColor,
          fontSize: `${fontSize}px`,
          width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放
          lineHeight: `${fontSize * 20 / 14}px`,
          borderRadius: `${fontSize * 3 / 14}px`,
        }
      },
      splitorStyle() {
        const {
          splitorColor,
          fontSize,
          backgroundColor
        } = this
        return {
          color: splitorColor,
          fontSize: `${fontSize * 12 / 14}px`,
          margin: backgroundColor ? `${fontSize * 4 / 14}px` : ''
        }
      }
    },
    watch: {
      day(val) {
        this.changeFlag()
      },
      hour(val) {
        this.changeFlag()
      },
      minute(val) {
        this.changeFlag()
      },
      second(val) {
        this.changeFlag()
      },
      start: {
        immediate: true,
        handler(newVal, oldVal) {
          if (newVal) {
            this.startData();
          } else {
            if (!oldVal) return
            clearInterval(this.timer)
          }
        }

      }
    },
    created: function(e) {
      this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
      this.countDown()
    },
    // #ifndef VUE3
    destroyed() {
      clearInterval(this.timer)
    },
    // #endif
    // #ifdef VUE3
    unmounted() {
      clearInterval(this.timer)
    },
    // #endif
    methods: {
      toSeconds(timestamp, day, hours, minutes, seconds) {
        if (timestamp) {
          return timestamp - parseInt(new Date().getTime() / 1000, 10)
        }
        return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
      },
      timeUp() {
        clearInterval(this.timer)
        this.$emit('timeup')
      },
      countDown() {
        let seconds = this.seconds
        let [day, hour, minute, second] = [0, 0, 0, 0]
        if (seconds > 0) {
          day = Math.floor(seconds / (60 * 60 * 24))
          hour = Math.floor(seconds / (60 * 60)) - (day * 24)
          minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
          second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
        } else {
          this.timeUp()
        }
        if (day < 10) {
          day = '0' + day
        }
        if (hour < 10) {
          hour = '0' + hour
        }
        if (minute < 10) {
          minute = '0' + minute
        }
        if (second < 10) {
          second = '0' + second
        }
        this.d = day
        this.h = hour
        this.i = minute
        this.s = second
      },
      startData() {
        this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
        if (this.seconds <= 0) {
          this.seconds = this.toSeconds(0, 0, 0, 0, 0)
          this.countDown()
          return
        }
        clearInterval(this.timer)
        this.countDown()
        this.timer = setInterval(() => {
          this.seconds--
          if (this.seconds < 0) {
            this.timeUp()
            return
          }
          this.countDown()
        }, 1000)
      },
      update() {
        this.startData();
      },
      changeFlag() {
        if (!this.syncFlag) {
          this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
          this.startData();
          this.syncFlag = true;
        }
      }
    }
  }
</script>
<style lang="scss" scoped>
  $font-size: 14px;

  .uni-countdown {
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;

    &__splitor {
      margin: 0 2px;
      font-size: $font-size;
      color: #333;
    }

    &__number {
      border-radius: 3px;
      text-align: center;
      font-size: $font-size;
    }
  }
</style>